#ifndef ASKSHDFIASUEGHFI2323J2_
#define ASKSHDFIASUEGHFI2323J2_

#include "alexNet.hpp"
#include "define.hpp"
using namespace PiaCNN;


bool create_cnn_model_ocr_alex(PiaAlexNet &Model, string strPath)
{
	// Load parameters from a "*.npz" file
	if (access(strPath.c_str(), 0) == -1) {  
        cout<< ">> error. LoadParameters() File not exists. Info = " 
        	<< strPath.c_str() << endl;  
        return false;  
    } 
    cnpy::npz_t npzData = cnpy::npz_load(strPath);
	// Layer 1 : convolution layer, padding = 'SAME', stride = 1
	int nL0InRows  = 28;
	int nL0InCols  = 28;
	int nL0InChan  = 1;
	int nL0KerRows = 5;
	int nL0KerCols = 5;
	int nL0KerNum  = 12;
	AlexLayer L0;
	L0.Type = LAYER_CONV2D;
	L0.Conv.Create(nL0InRows, nL0InCols, nL0InChan, nL0KerRows, nL0KerCols, nL0KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	PiaConv2dW W; 
	PiaConv2dB B;
	W.cvt(npzData["W1"]);
	B.cvt(npzData["B1"]);
	L0.Conv.LoadWandB(W, B);
	Model.Push(L0);
	// Layer 2 : convolution layer, padding = 'SAME', stride = 1
	int nL1InRows  = L0.Conv.nOutputRows;
	int nL1InCols  = L0.Conv.nOutputCols;
	int nL1InChan  = L0.Conv.nOutputChan;
	int nL1KerRows = 5;
	int nL1KerCols = 5;
	int nL1KerNum  = 24;
	AlexLayer L1;
	L1.Type = LAYER_CONV2D;
	L1.Conv.Create(nL1InRows, nL1InCols, nL1InChan, nL1KerRows, nL1KerCols, nL1KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	W.cvt(npzData["W2"]);
	B.cvt(npzData["B2"]);
	L1.Conv.LoadWandB(W, B);
	Model.Push(L1);
	// Layer 2 : max pooling, padding = 'SAME'
	int nL2InRows  = L1.Conv.nOutputRows;
	int nL2InCols  = L1.Conv.nOutputCols;
	int nL2InChan  = L1.Conv.nOutputChan;
	int nL2KerRows = 2;
	int nL2KerCols = 2;
	int nL2Stride1 = 2;
	int nL2Stride2 = 2;
	int nL2Type    = POOLING_MAX;
	AlexLayer L2;
	L2.Type = LAYER_POOLING;
	L2.Pool.Create(nL2InRows, nL2InCols, nL2InChan, nL2KerCols, nL2KerCols, nL2Stride1, nL2Stride2, 
				   nL2Type);
	Model.Push(L2);
	// Layer 3 : convolution layer, padding = 'SAME', stride = 1
	int nL3InRows  = L2.Pool.nOutputRows;
	int nL3InCols  = L2.Pool.nOutputCols;
	int nL3InChan  = L2.Pool.nOutputChan;
	int nL3KerRows = 3;
	int nL3KerCols = 3;
	int nL3KerNum  = 36;
	AlexLayer L3;
	L3.Type = LAYER_CONV2D;
	L3.Conv.Create(nL3InRows, nL3InCols, nL3InChan, nL3KerRows, nL3KerCols, nL3KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	W.cvt(npzData["W3"]); 
	B.cvt(npzData["B3"]); 
	L3.Conv.LoadWandB(W, B);
	Model.Push(L3);
	// Layer 3 : max pooling, padding = 'SAME'
	int nL4InRows  = L3.Conv.nOutputRows;
	int nL4InCols  = L3.Conv.nOutputCols;
	int nL4InChan  = L3.Conv.nOutputChan; 
	int nL4KerRows = 2;
	int nL4KerCols = 2;
	int nL4Stride1 = 2;
	int nL4Stride2 = 2;
	int nL4Type    = POOLING_MAX;
	AlexLayer L4;
	L4.Type = LAYER_POOLING;
	L4.Pool.Create(nL4InRows, nL4InCols, nL4InChan, nL4KerCols, nL4KerCols, nL4Stride1, nL4Stride2, 
				   nL4Type);
	Model.Push(L4);
	// Layer 4 : full connection
	int nL5InRows  = L4.Pool.nOutputRows;
	int nL5InCols  = L4.Pool.nOutputCols;
	int nL5InChan  = L4.Pool.nOutputChan;
	int nL5VctLen  = nL5InRows * nL5InCols * nL5InChan;
	int nL5NeuNum  = 256;
	int nL5ActFun  = ACTIVE_FUNC_RELU;
	AlexLayer L5;
	L5.Type = LAYER_FULL;
	L5.Full.Create(nL5VctLen, nL5NeuNum, nL5ActFun);
	PiaFullW fW;
	PiaFullB fB;
	fW.cvt(npzData["W4"]); 
	fB.cvt(npzData["B4"]); 
	L5.Full.LoadWandB(fW, fB);
	Model.Push(L5);
	// Layer 5 : full connection (output)
	int nL6VctLen  = nL5NeuNum;
	int nL6NeuNum  = 10;
	int nL6ActFun  = ACTIVE_FUNC_SOFTMAX;
	AlexLayer L6;
	L6.Type = LAYER_FULL;
	L6.Full.Create(nL6VctLen, nL6NeuNum, nL6ActFun);
	fW.cvt(npzData["W5"]); 
	fB.cvt(npzData["B5"]); 
	L6.Full.LoadWandB(fW, fB); 
	Model.Push(L6);
	
	return true;
}


bool create_cnn_model_ocr_space2depth(PiaAlexNet &Model, string strPath)
{
	// Load parameters from a "*.npz" file
	if (access(strPath.c_str(), 0) == -1) {  
        cout<< ">> error. LoadParameters() File not exists. Info = " 
        	<< strPath.c_str() << endl;  
        return false;  
    } 
    cnpy::npz_t npzData = cnpy::npz_load(strPath);
	// Layer 1 : convolution layer, padding = 'SAME', stride = 1
	int nL0InRows  = 14;
	int nL0InCols  = 14;
	int nL0InChan  = 4;
	int nL0KerRows = 3;
	int nL0KerCols = 3;
	int nL0KerNum  = 12;
	AlexLayer L0;
	L0.Type = LAYER_CONV2D;
	L0.Conv.Create(nL0InRows, nL0InCols, nL0InChan, nL0KerRows, nL0KerCols, nL0KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	PiaConv2dW W; 
	PiaConv2dB B;
	W.cvt(npzData["W1"]);
	B.cvt(npzData["B1"]);
	L0.Conv.LoadWandB(W, B);
	Model.Push(L0);
	// Layer 2 : convolution layer, padding = 'SAME', stride = 1
	int nL1InRows  = L0.Conv.nOutputRows;
	int nL1InCols  = L0.Conv.nOutputCols;
	int nL1InChan  = L0.Conv.nOutputChan;
	int nL1KerRows = 3;
	int nL1KerCols = 3;
	int nL1KerNum  = 24;
	AlexLayer L1;
	L1.Type = LAYER_CONV2D;
	L1.Conv.Create(nL1InRows, nL1InCols, nL1InChan, nL1KerRows, nL1KerCols, nL1KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	W.cvt(npzData["W2"]);
	B.cvt(npzData["B2"]);
	L1.Conv.LoadWandB(W, B);
	Model.Push(L1);
	// Layer 3 : convolution layer, padding = 'SAME', stride = 1
	int nL3InRows  = L1.Conv.nOutputRows;
	int nL3InCols  = L1.Conv.nOutputCols;
	int nL3InChan  = L1.Conv.nOutputChan;
	int nL3KerRows = 3;
	int nL3KerCols = 3;
	int nL3KerNum  = 36;
	AlexLayer L3;
	L3.Type = LAYER_CONV2D;
	L3.Conv.Create(nL3InRows, nL3InCols, nL3InChan, nL3KerRows, nL3KerCols, nL3KerNum,
				   1,1,1,1, ACTIVE_FUNC_RELU, "");
	W.cvt(npzData["W3"]); 
	B.cvt(npzData["B3"]); 
	L3.Conv.LoadWandB(W, B);
	Model.Push(L3);
	// Layer 3 : max pooling, padding = 'SAME'
	int nL4InRows  = L3.Conv.nOutputRows;
	int nL4InCols  = L3.Conv.nOutputCols;
	int nL4InChan  = L3.Conv.nOutputChan; 
	int nL4KerRows = 2;
	int nL4KerCols = 2;
	int nL4Stride1 = 2;
	int nL4Stride2 = 2;
	int nL4Type    = POOLING_MAX;
	AlexLayer L4;
	L4.Type = LAYER_POOLING;
	L4.Pool.Create(nL4InRows, nL4InCols, nL4InChan, nL4KerCols, nL4KerCols, nL4Stride1, nL4Stride2, 
				   nL4Type);
	Model.Push(L4);
	// Layer 4 : full connection
	int nL5InRows  = L4.Pool.nOutputRows;
	int nL5InCols  = L4.Pool.nOutputCols;
	int nL5InChan  = L4.Pool.nOutputChan;
	int nL5VctLen  = nL5InRows * nL5InCols * nL5InChan;
	int nL5NeuNum  = 256;
	int nL5ActFun  = ACTIVE_FUNC_RELU;
	AlexLayer L5;
	L5.Type = LAYER_FULL;
	L5.Full.Create(nL5VctLen, nL5NeuNum, nL5ActFun);
	PiaFullW fW;
	PiaFullB fB;
	fW.cvt(npzData["W4"]); 
	fB.cvt(npzData["B4"]); 
	L5.Full.LoadWandB(fW, fB);
	Model.Push(L5);
	// Layer 5 : full connection (output)
	int nL6VctLen  = nL5NeuNum;
	int nL6NeuNum  = 10;
	int nL6ActFun  = ACTIVE_FUNC_SOFTMAX;
	AlexLayer L6;
	L6.Type = LAYER_FULL;
	L6.Full.Create(nL6VctLen, nL6NeuNum, nL6ActFun);
	fW.cvt(npzData["W5"]); 
	fB.cvt(npzData["B5"]); 
	L6.Full.LoadWandB(fW, fB); 
	Model.Push(L6);
	
	return true;
}

#endif

































